package com.qc31.monitorlib.ui.carsmonitor

import android.os.Handler
import android.os.HandlerThread
import android.os.Looper
import android.os.Message
import autodispose2.autoDispose
import com.amap.api.maps.AMap
import com.amap.api.maps.model.LatLng
import com.amap.api.maps.model.LatLngBounds
import com.qc31.baselib.auto.AutoDisposeViewModel
import com.qc31.baselib.utils.CacheMMKV
import com.qc31.baselib.utils.isNoLocation
import com.qc31.comlib.UserConstant
import com.qc31.comlib.entity.GpsDetail
import com.qc31.comlib.entity.GpsSimple
import com.qc31.comlib.entity.Legend
import com.qc31.comlib.net.ServiceHelper
import com.qc31.monitorlib.R
import com.qc31.monitorlib.clusters.ClusterItem
import io.reactivex.rxjava3.core.Flowable
import io.reactivex.rxjava3.disposables.Disposable
import io.reactivex.rxjava3.subjects.PublishSubject
import java.util.concurrent.TimeUnit

/** @author joker @date 2022/8/1$ 10:24$ */
class MultiMonitorViewModel : AutoDisposeViewModel() {
    //车队ID
    var teamId = ""

    //车辆ID
    var carId = ""

    //当前车辆下标
    private var index = 0

    //是否显示在一屏与线程
    var isBounds = true

    //定时观察者
    private var subscribe: Disposable? = null

    //是否是刷新
    private var isRefresh = false

    //是否显示卡片数据
    private var isShowCard = false

    //分类后数量集合
    val typeNum = ArrayList<Int>()

    //聚合点集合
    private val clusters = arrayListOf<ClusterItem>()

    //是否展示某车辆
    var isOneCar = false

    //定位数据
    var gpsDetail: GpsDetail? = null

    //定位结果
    private val locationSub by lazy { PublishSubject.create<Boolean>() }
    fun locationObserver() = locationSub.hide()

    //图例
    private val legendSub by lazy { PublishSubject.create<ArrayList<Legend>>() }
    fun legendObserver() = legendSub.hide()

    //聚合点
    private val clustersSub by lazy { PublishSubject.create<ArrayList<ClusterItem>>() }
    fun clustersObserver() = clustersSub.hide()

    //分类数据
    private val gpsSub by lazy { PublishSubject.create<ArrayList<ArrayList<GpsSimple>>>() }
    fun gpsObserver() = gpsSub.hide()
    private val gpsList = ArrayList<ArrayList<GpsSimple>>()


    //全部定位集合
    private val locations = arrayListOf<GpsSimple>()
    private val runCars = ArrayList<GpsSimple>()
    private val stopCars = ArrayList<GpsSimple>()
    private val offlineCars = ArrayList<GpsSimple>()
    private val arrearsCars = ArrayList<GpsSimple>()
    private val alarmCars = ArrayList<GpsSimple>()
    private val locationCars = ArrayList<GpsSimple>()


    /////////////////////////////////上一辆 当前 下一辆/////////////////////////////////////////////////////////


    /** 上一辆 */
    fun previous() {
        index -= 1
        if (index < 0) {
            index = 0
            toast(R.string.toast_car_top)
            return
        }
        val carInfo = locations[index]
        if (isNoLocation(carInfo.state)) {
            previous()
        } else {
            carId = carInfo.carId
        }
        getLocation()
    }

    /** 当前 */
    fun nowCar() {
        index = getIndexById(carId)
        getLocation()
        isOneCar = true
    }

    /** 下一辆 */
    fun nextCar() {
        index += 1
        if (index >= locations.size) {
            index = locations.size - 1
            toast(R.string.toast_car_bottom)
            return
        }
        val carInfo = locations[index]
        if (isNoLocation(carInfo.state)) {
            nextCar()
        } else {
            carId = carInfo.carId
        }
        getLocation()

    }

    /** Get all cars */
    fun getAllCars() {
        teamId = ""
        stopTime()
        startTime()
    }

    /** 查询当前车辆下标 */
    private fun getIndexById(carId: String): Int {
        for ((index, entity) in locations.withIndex()) {
            if (carId == entity.carId) return index
        }
        return 0
    }

    /**
     * 获取当前屏幕区域
     *
     * @return
     */
    fun getBounds(): LatLngBounds? {
        val builder = LatLngBounds.builder()
        clusters.forEach { builder.include(it.position) }
        return builder.build()
    }

    /**
     * 根据多个点获取当前屏幕区域
     *
     * @return
     */
    fun getBounds(vararg latLng: LatLng): LatLngBounds {
        val builder = LatLngBounds.builder()
        latLng.forEach { builder.include(it) }
        return builder.build()
    }

    /////////////////////////////////网络请求/////////////////////////////////////////////////////////
    //开始定时刷新
    fun startTime() {
        subscribe = Flowable.interval(0, refreshTime.toLong(), TimeUnit.SECONDS)
            .autoDispose(this).subscribe {
                getCarsByTeam()
                if (isOneCar) {
                    getLocation()
                }
            }
    }

    //结束定时刷新
    fun stopTime() {
        if (subscribe?.isDisposed == false) subscribe?.dispose()
        subscribe = null
    }

    /** 刷新单辆车 car */
    fun refreshCar() {
        isRefresh = true
        getLocation()
    }


    /** 通过TeamId查询车辆建议信息 */
    private fun getCarsByTeam() {
        ServiceHelper.getRepository().getGpsR(teamId, "", simple = true, filter = false)
            .autoDispose(this).subscribe({
                if (it.isNotEmpty()) {
                    locations.clear()
                    locations.addAll(it)

                    var msg = Message.obtain()
                    msg.what = TYPE_LOCATIONS
                    carsHandle?.sendMessage(msg)

                    if (isShowCard) {
                        msg = Message.obtain()
                        msg.what = TYPE_CLASSIFY
                        carsHandle?.sendMessage(msg)
                    }
                } else {
                    typeNum.clear()
                    for (i in 0..5) {
                        typeNum.add(0)
                    }
                    toastLoading(false)
                }
            }, error)
    }

    /** 查询单车的全部信息 */
    private fun getLocation() {
        if (isCarEmpty()) return
        ServiceHelper.getRepository().getGpsRInfo("", carId).autoDispose(this)
            .subscribe({
                if (it.isNullOrEmpty()) {
                    toast(R.string.toast_no_location_msg)
                    gpsDetail = null
                } else {
                    if (isRefresh) {
                        isRefresh = false
                        toast(R.string.toast_refresh_success)
                    }
                    gpsDetail = it[0]
                    locationSub.onNext(true)
                }
                toastLoading(false)
            }, error)
    }

    /** 查询单车的图例信息 */
    fun getLegend() {
        if (isCarEmpty()) return
        ServiceHelper.getRepository().getLegend(carId)
            .autoDispose(this)
            .subscribe({
                if (isHasListData(it)) return@subscribe
                if (UserConstant.current_ip == "113.105.152.93") {
                    val filter = it.filter { legens ->
                        legens.stateIndex != "6"
                    }
                    legendSub.onNext(filter as ArrayList<Legend>)
                } else {
                    legendSub.onNext(it)
                }
            }, error)
    }

    /**
     * 判断是否已经选择车辆
     *
     * @return
     */
    private fun isCarEmpty(): Boolean {
        val empty = carId.isEmpty()
        if (empty) toast(R.string.hint_toast_choose_car)
        return empty
    }

    /**
     * 判断是否已经选择车队
     *
     * @return
     */
    private fun isTeamIdEmpty(): Boolean {
        val empty = teamId.isEmpty()
        if (empty) toast(R.string.hint_toast_choose_team)
        return empty
    }

    /**
     * 设置是否展示卡片数据
     *
     * @param isShowCard
     */
    fun setShowCard(isShowCard: Boolean) {
        this.isShowCard = isShowCard
        if (isShowCard) {
            toastLoading(true)
            val msg = Message.obtain()
            msg.what = TYPE_CLASSIFY
            carsHandle?.sendMessage(msg)
        }
    }


    /////////////////////////////////线程处理/////////////////////////////////////////////////////////
    companion object {
        //处理聚合
        const val TYPE_LOCATIONS = 0

        //处理分类
        const val TYPE_CLASSIFY = 1
    }

    private var carsHandle: DataHandle? = null
    private val carsThread by lazy { HandlerThread("carsThread") }

    /** 初始化处理线程 */
    private fun initHandle() {
        carsThread.start()
        carsHandle = DataHandle(carsThread.looper)
    }

    //结束处理线程
    private fun stopHandle() {
        carsHandle?.removeCallbacksAndMessages(null)
        carsThread.quit()
    }

    inner class DataHandle(looper: Looper) : Handler(looper) {
        override fun handleMessage(msg: Message) {
            super.handleMessage(msg)
            if (msg.what == TYPE_LOCATIONS) {
                clusters.clear()
                locations.filter { it.glat.isNotEmpty() }.forEach {
                    clusters.add(
                        ClusterItem(
                            LatLng(it.glat.toDouble(), it.glng.toDouble()),
                            it.carId, it.carName, it.carPlate,
                            it.iconLink, it.speed, it.state, it.drct
                        )
                    )
                }
                clustersSub.onNext(clusters)
            } else {
                typeNum.clear()
                runCars.clear()
                stopCars.clear()
                offlineCars.clear()
                alarmCars.clear()
                arrearsCars.clear()
                locationCars.clear()
                for (entity in locations) {
                    when (entity.state) {
                        "1" -> {
                            offlineCars.add(entity)
                        }
                        "2" -> {
                            offlineCars.add(entity)
                            arrearsCars.add(entity)
                        }
                        "3" -> {
                            offlineCars.add(entity)
                        }
                        "4" -> {
                            offlineCars.add(entity)
                            alarmCars.add(entity)
                        }
                        "13" -> {
                            locationCars.add(entity)
                        }
                        "6" -> {
                            arrearsCars.add(entity)
                        }
                        "7" -> {
                            runCars.add(entity)
                        }
                        "8" -> {
                            runCars.add(entity)
                            alarmCars.add(entity)
                        }
                        "9", "10" -> {
                            stopCars.add(entity)
                        }
                        "11", "12" -> {
                            alarmCars.add(entity)
                            stopCars.add(entity)
                        }
                    }

                }

                gpsList.clear()
                gpsList.add(locations)
                gpsList.add(offlineCars)
                gpsList.add(runCars)
                gpsList.add(stopCars)
                gpsList.add(alarmCars)
                gpsList.add(arrearsCars)
                gpsList.add(locationCars)

                typeNum.add(locations.size)
                typeNum.add(offlineCars.size)
                typeNum.add(runCars.size)
                typeNum.add(stopCars.size)
                typeNum.add(alarmCars.size)
                typeNum.add(arrearsCars.size)
                typeNum.add(locationCars.size)

                gpsSub.onNext(gpsList)
                toastLoading(false)
            }
        }
    }

    /////////////////////////////////地图相关设置//////////////////////////////////////////////////////////


    //刷新时间
    var refreshTime = 10
    fun saveRefresh(refreshTime: Int) {
        this.refreshTime = refreshTime
        CacheMMKV.encode("refresh_time", refreshTime)
        if (teamId.isEmpty()) return
        stopTime()
        startTime()
    }

    //是否显示车名
    var isCarName = false
    fun saveCarName(isCarName: Boolean) {
        this.isCarName = isCarName
        CacheMMKV.encode("Cars_isCarName", isCarName)
    }

    //是否标准地图
    var mapType = AMap.MAP_TYPE_NORMAL
    fun saveMapType(mapType: Int) {
        this.mapType = mapType
        CacheMMKV.encode("Cars_MapType", mapType)
    }

    //是否显示路况
    var isTraffic = false
    fun saveTraffic() {
        isTraffic = !isTraffic
        CacheMMKV.encode("Cars_isTraffic", isTraffic)
    }

    //是否展示弹窗
    var isShowPopup = false
    fun saveShowPopup(isShowPopup: Boolean) {
        this.isShowPopup = isShowPopup
        CacheMMKV.encode("isShowPopup", isShowPopup)
    }

    //是否聚合
    var isCluster = false
    fun saveCluster(isCluster: Boolean) {
        this.isCluster = isCluster
        CacheMMKV.encode("isCluster", isCluster)
    }


    init {
        isCarName = CacheMMKV.decodeBoolean("Cars_isCarName")
        isTraffic = CacheMMKV.decodeBoolean("Cars_isTraffic")
        isShowPopup = CacheMMKV.decodeBoolean("isShowPopup", true)
        isCluster = CacheMMKV.decodeBoolean("isCluster", true)
        refreshTime = CacheMMKV.decodeInt("refresh_time", 10)
        mapType = CacheMMKV.decodeInt("Cars_MapType", AMap.MAP_TYPE_NORMAL)
        initHandle()
    }

    override fun onCleared() {
        super.onCleared()
        stopHandle()
    }
}